/*
 * Add interval between SRIO packages.
 *
 * The program cofigure the Mapping config register to add some time
 * between each SRIO packages. This feature is optional to adapt some 
 * slower performance SRIO device.
 */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <rio_mport_lib.h>

#ifdef __cplusplus
extern "C" {
#endif


#define PRB0400_MAPPING_CFG1	0x42004
#define MAPPING_CFG1_ARB_GAP_EN 0x40000000

#define PRB0400_MAPPING_CFG3	0x4200c
#define MAPPING_ARB_GAP_PAT	    0x000ff000

#define ARB_GAP_CFG_MAX         1020


static void usage(char *program)
{
	printf("%s - Add some time between SRIO packages\n", program);
	printf("Usage:\n");
	printf("	%s [options]\n", program);
	printf("Options are:\n");
	printf("    <mport> local mport device index\n");
	printf("    <interval> 0-disable SRIO package gap feature  others-srio package interval vaule(ns, max %d)\n",ARB_GAP_CFG_MAX);
	printf("    [debug] enable debug output\n");
	printf("\n");
}


int main(int argc, char **argv)
{	
	int fd;
	uint32_t mport_id = 0;
	int rc = EXIT_SUCCESS;
	uint32_t data;	
	uint32_t op_size = 4;
	static uint32_t interval,srio_gap_cfg;
	static uint32_t debug_on;
	
	/* Parse console arguments */
	if (argc < 3) {
		usage(argv[0]);		
		exit(EXIT_FAILURE);
	}

	if(argc > 3)
		debug_on = 1;
	
	mport_id  = strtoul(argv[1], NULL, 0);

	interval  = strtoul(argv[2], NULL, 0);

	if(interval > ARB_GAP_CFG_MAX)
		interval = ARB_GAP_CFG_MAX;
	
	fd = rio_mport_open(mport_id, 0);
	if (fd < 0) {
		printf("Unable to open mport%d device err=%d\n",
			mport_id, errno);
		exit(EXIT_FAILURE);
	}

	rc = rio_lcfg_read(fd, PRB0400_MAPPING_CFG1, op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;	
		goto out;
	}
	
	if(interval){
		rio_lcfg_write(fd, PRB0400_MAPPING_CFG1, op_size, data | MAPPING_CFG1_ARB_GAP_EN);
		if(debug_on)
			printf("SRIO package feature enabled\n");

		rc = rio_lcfg_read(fd, PRB0400_MAPPING_CFG3, op_size, &data);
		if (rc){
			printf("Read Error %d\n", rc);
			rc = EXIT_FAILURE;	
			goto out;
		}
		srio_gap_cfg = ((interval/4) << 12)&MAPPING_ARB_GAP_PAT;//8bit gap config field, 1 -> 4ns
		rio_lcfg_write(fd, PRB0400_MAPPING_CFG3, op_size, (data & (~MAPPING_ARB_GAP_PAT)) | srio_gap_cfg);
		if(debug_on)
			printf("SRIO package interval:%d, srio_gap_cfg:0x%x\n",interval,srio_gap_cfg);
		
	}else{
		rio_lcfg_write(fd, PRB0400_MAPPING_CFG1, op_size, data & (~MAPPING_CFG1_ARB_GAP_EN));
		printf("SRIO package gap feature disabled\n");
	}

out:
	if(rc == 0){
		if(interval)
			printf("SRIO package interval set as %d ns success\n",(srio_gap_cfg>>12)*4);
	}
	else{
		printf("SRIO package interval set failed, ret:%d\n",rc);
	}

	/* Close the mport fd */
	close(fd);
	exit(rc);
}

#ifdef __cplusplus
}
#endif

